/**
 * Grep MCP Server - GitHub Code Search via grep.app API
 * Supports both stdio and SSE transport modes
 */

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from '@modelcontextprotocol/sdk/types.js';

import { executeGrepQuery } from './tools/grep-query.js';
import { executeGiteeQuery } from './tools/gitee-query.js';
import { SearchParams } from './types.js';

/**
 * Server configuration interface
 */
interface ServerConfig {
  transport: 'stdio' | 'sse';
  host?: string;
  port?: number;
}

/**
 * Parse command line arguments to determine server configuration
 */
function parseServerConfig(): ServerConfig {
  const args = process.argv.slice(2);
  const config: ServerConfig = { transport: 'stdio' };

  for (let i = 0; i < args.length; i++) {
    const arg = args[i];
    
    switch (arg) {
      case '--transport':
        const transport = args[i + 1];
        if (transport === 'stdio' || transport === 'sse') {
          config.transport = transport;
        }
        i++; // Skip next argument
        break;
        
      case '--host':
        config.host = args[i + 1];
        i++; // Skip next argument
        break;
        
      case '--port':
        const port = parseInt(args[i + 1], 10);
        if (!isNaN(port)) {
          config.port = port;
        }
        i++; // Skip next argument
        break;
        
      case '--help':
        console.log(`
Grep MCP Server - GitHub Code Search

Usage: grep-mcp [options]

Options:
  --transport <stdio|sse>  Transport mode (default: stdio)
  --host <host>           Host for SSE transport (default: localhost)
  --port <port>           Port for SSE transport (default: 3000)
  --help                  Show this help message

Examples:
  grep-mcp                           # Run with stdio transport
  grep-mcp --transport sse           # Run with SSE transport on localhost:3000
  grep-mcp --transport sse --port 8080  # Run with SSE transport on port 8080
        `);
        process.exit(0);
        break;
    }
  }

  return config;
}

/**
 * Create and configure the MCP server
 */
function createServer(): Server {
  const server = new Server(
    {
      name: 'grep-mcp-ts',
      version: '1.1.0',
    },
    {
      capabilities: {
        tools: {},
      },
    }
  );

  // Register both grep_query and gitee_query tools
  server.setRequestHandler(ListToolsRequestSchema, async () => {
    return {
      tools: [
        {
          name: 'grep_query',
          description: 'Search GitHub code using grep.app API. This tool enables AI assistants to search through GitHub repositories for specific code patterns using grep.app\'s powerful search index. It returns formatted results with repository information, file paths, and code snippets.',
          inputSchema: {
            type: 'object',
            properties: {
              query: {
                type: 'string',
                description: 'The search query string to find in GitHub repositories',
              },
              language: {
                type: 'string',
                description: 'Optional programming language filter (e.g., "Python", "JavaScript")',
              },
              repo: {
                type: 'string',
                description: 'Optional repository filter in format "owner/repo" (e.g., "fastapi/fastapi")',
              },
              path: {
                type: 'string',
                description: 'Optional path filter to search within specific directories (e.g., "src/")',
              },
            },
            required: ['query'],
          },
        },
        {
          name: 'gitee_query',
          description: 'Search Gitee code using Gitee search API. This tool enables AI assistants to search through Gitee repositories for specific code patterns using Gitee\'s search functionality. It returns formatted results with repository information, file paths, and code snippets.',
          inputSchema: {
            type: 'object',
            properties: {
              query: {
                type: 'string',
                description: 'The search query string to find in Gitee repositories',
              },
              language: {
                type: 'string',
                description: 'Optional programming language filter (e.g., "Python", "JavaScript")',
              },
              repo: {
                type: 'string',
                description: 'Optional repository filter in format "owner/repo" (e.g., "openeuler/kernel")',
              },
              path: {
                type: 'string',
                description: 'Optional path filter to search within specific directories (e.g., "src/")',
              },
            },
            required: ['query'],
          },
        },
      ],
    };
  });

  // Handle tool execution
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;

    if (name === 'grep_query') {
      try {
        if (!args || typeof args !== 'object') {
          throw new McpError(ErrorCode.InvalidParams, 'Invalid arguments provided');
        }

        const searchParams: SearchParams = {
          query: args.query as string,
        };

        // Only add optional properties if they exist and are not undefined
        if (args.language && typeof args.language === 'string') {
          searchParams.language = args.language;
        }
        if (args.repo && typeof args.repo === 'string') {
          searchParams.repo = args.repo;
        }
        if (args.path && typeof args.path === 'string') {
          searchParams.path = args.path;
        }

        const result = await executeGrepQuery(searchParams);
        
        return {
          content: [
            {
              type: 'text',
              text: result,
            },
          ],
        };
      } catch (error) {
        throw new McpError(
          ErrorCode.InternalError,
          `Grep query failed: ${error instanceof Error ? error.message : String(error)}`
        );
      }
    }

    if (name === 'gitee_query') {
      try {
        if (!args || typeof args !== 'object') {
          throw new McpError(ErrorCode.InvalidParams, 'Invalid arguments provided');
        }

        const searchParams: SearchParams = {
          query: args.query as string,
        };

        // Only add optional properties if they exist and are not undefined
        if (args.language && typeof args.language === 'string') {
          searchParams.language = args.language;
        }
        if (args.repo && typeof args.repo === 'string') {
          searchParams.repo = args.repo;
        }
        if (args.path && typeof args.path === 'string') {
          searchParams.path = args.path;
        }

        const result = await executeGiteeQuery(searchParams);
        
        return {
          content: [
            {
              type: 'text',
              text: result,
            },
          ],
        };
      } catch (error) {
        throw new McpError(
          ErrorCode.InternalError,
          `Gitee query failed: ${error instanceof Error ? error.message : String(error)}`
        );
      }
    }

    throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
  });

  return server;
}

/**
 * Run server with stdio transport
 */
async function runStdioServer(): Promise<void> {
  const server = createServer();
  const transport = new StdioServerTransport();
  
  await server.connect(transport);
  console.error('Grep MCP Server running on stdio transport');
}

/**
 * Run server with SSE transport
 * Note: SSE transport may not be available in current MCP TypeScript SDK
 */
async function runSSEServer(host: string = 'localhost', port: number = 3000): Promise<void> {
  console.error(`SSE transport is not yet available in the MCP TypeScript SDK.`);
  console.error(`Requested configuration: ${host}:${port}`);
  console.error('Falling back to stdio transport...');
  await runStdioServer();
}

/**
 * Main server startup function
 */
async function runServer(): Promise<void> {
  const config = parseServerConfig();
  
  console.error(`Starting Grep MCP Server with ${config.transport} transport...`);
  
  if (config.transport === 'sse') {
    await runSSEServer(config.host, config.port);
  } else {
    await runStdioServer();
  }
}

// Handle graceful shutdown
process.on('SIGINT', async () => {
  console.error('Shutting down Grep MCP Server...');
  process.exit(0);
});

process.on('SIGTERM', async () => {
  console.error('Shutting down Grep MCP Server...');
  process.exit(0);
});

// Handle uncaught exceptions
process.on('uncaughtException', (error) => {
  console.error('Uncaught exception:', error);
  process.exit(1);
});

process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled rejection at:', promise, 'reason:', reason);
  process.exit(1);
});

// Export for use in index.ts
export { runServer };

// Start the server if this file is run directly
if (import.meta.url === `file://${process.argv[1]}`) {
  runServer().catch((error) => {
    console.error('Failed to start server:', error);
    process.exit(1);
  });
}